/**
 * 2017年12月6日
 */
package exp.algorithm.gbdt;

import exp.util.DatasetsUtil;
import weka.classifiers.AbstractClassifier;
import weka.classifiers.Classifier;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.functions.SMO;
import weka.classifiers.trees.DecisionStump;
import weka.classifiers.trees.RandomTree;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;

/**
 * @author Alex
 *
 */
public class OneHotEncodingClassifier extends AbstractClassifier{

	int  numClassifiers = 100;
	Classifier[] classifiers = null;
	Classifier linearClassifier = new SMO();
	Instances meta = null;
	int classNum = -1;
	int metaAttNum;
	@Override
	public void buildClassifier(Instances data) throws Exception {
		classifiers = new Classifier[numClassifiers];
		Instances temp = new Instances(data);
		for(int i = 0;i<numClassifiers ; i++){
			 RandomTree rt = new RandomTree();
			 //自定义每棵树的参数
			 //rt.setKValue(0);
			 //==============
			 classifiers[i] = rt;
			 classifiers[i].buildClassifier(temp);
		}
		int num = data.numInstances();
		classNum = data.numClasses();
		metaAttNum = classNum * numClassifiers;
		meta = DatasetsUtil.initInstancesWithParmas("meta", metaAttNum, "meta_", num, true,(Attribute)data.classAttribute().copy());
		for(int i = 0;i<num;i++){
			double  [] vals = new double[metaAttNum+1];
			for(int j=0;j<classifiers.length;j++){
				double res [] = toOneHotEncoding(classifiers[j].distributionForInstance(data.instance(i))); 
				System.arraycopy(res, 0, vals, j*classNum, res.length);
			}
			vals[vals.length-1] = data.instance(i).classValue();
			DenseInstance di = new DenseInstance(1.0, vals);
			di.setDataset(meta);
			meta.add(di);
		}
		linearClassifier.buildClassifier(meta);
	}
	
	private double[] toOneHotEncoding(double [] d){
		return d;
	}
	
	@Override
	public double[] distributionForInstance(Instance instance) throws Exception {
		double res[] = new double [ this.metaAttNum +1 ];
		for(int i= 0 ;i < this.numClassifiers;i++){
			System.arraycopy(classifiers[i].distributionForInstance(instance), 0, res, i*this.classNum, this.classNum);
		}
		DenseInstance denseinstances = new DenseInstance(1.0,res);
		denseinstances.setDataset(this.meta);
		return linearClassifier.distributionForInstance(denseinstances);
	}

}
